import React, { useEffect, useMemo, useRef, useState } from 'react';
import setting from './setting';
import JMap from './components/JMap';
import SelectMap from './components/SelectMap';
import JStyle from './components/JStyle';
import styled from './index.less';
import { previewWindowSize } from './utils/domEvent';

function EsthesiaDemo(props) {
  const { id, height, width, config, children, editable, coordinate, bigScreen } = props;
  const { mapServiceConfig, mapBaseConfig } = config;
  const { screenInfoData = {} } = bigScreen;
  const { zoomStyle, width: screenW, height: screenH } = screenInfoData;
  const { isShowMap, mapType } = mapServiceConfig;
  const { lng, lat, zoom, minZoom, maxZoom, dragable, zoomable, dragRotate, pitch } = mapBaseConfig;
  const [justMap, setJustMap] = useState(null);
  const jServerInfo = useRef();
  const customMapRef = useRef();
  const [ready, setReady] = useState(false);
  const [justMapKey, setJustMapKey] = useState(`${height}_${width}_${mapType}`);
  const divStyle = useMemo(() => {
    let resultStyle = { width, height };
    if (!editable && zoomStyle) {
      // 非编辑器页面（预览/发布），计算缩放级别
      // 目的：解决mapbox在缩放页面，定位偏移问题
      // 方法：反向缩放
      let w = width;
      let h = height;
      let newScaleX = 1;
      let newScaleY = 1;
      let newTop = coordinate.y;
      let newLeft = coordinate.x;
      const { scaleX, scaleY } = previewWindowSize({ zoomStyle, width: screenW, height: screenH });
      w *= scaleX;
      h *= scaleY;
      newScaleX = Math.floor((1 / scaleX) * 100) / 100;
      newScaleY = Math.floor((1 / scaleY) * 100) / 100;
      newLeft = (width - w) / 2;
      newTop = (height - h) / 2;
      resultStyle = {
        width: w,
        height: h,
        transform: `scaleX(${newScaleX}) scaleY(${newScaleY})`,
        position: 'absolute',
        top: `${newTop}px`,
        left: `${newLeft}px`,
      };
    }
    return resultStyle;
  }, [width, height, zoomStyle, screenW, screenH, coordinate]);

  // 获取缩放层级
  const getZoom = () => {
    if (zoom < minZoom) return minZoom;
    if (zoom > maxZoom) return maxZoom;
    return zoom;
  };

  // 处理map配置项
  const handleMapOptions = () => ({
    center: [lng, lat],
    minZoom,
    maxZoom,
    zoom: getZoom(),
    dragPan: dragable,
    scrollZoom: zoomable,
    doubleClickZoom: zoomable,
    dragRotate,
    pitch,
  });

  // 解析Just服务地址
  const justMapBaseURL = (jServer) => {
    if (!jServer) return false;
    const splitValue = jServer.split('/justserver');
    if (splitValue && splitValue.length !== 0) {
      const baseUrl = splitValue[0];
      if (baseUrl.indexOf('http') === -1) return false;
      return baseUrl;
    }
  };

  // 重新加载地图
  const reloadMap = (map) => {
    setJustMap(null);
    setTimeout(() => {
      setJustMap(map);
    }, 600);
  };

  // 处理地图类型标识
  const handleMapType = () => {
    if (mapType.includes(',')) {
      return mapType.split(',')[0];
    }
    return mapType;
  };

  // 地图加载完成
  const loadDone = (map) => {
    const mapStyle = JStyle[handleMapType(mapType)];
    if (mapStyle && mapStyle.init) {
      mapStyle
        .init(map.map, id, {
          customMap: customMapRef.current,
          pitch,
          param: mapType,
        })
        .then((customMap) => {
          customMap.on('complete', () => {
            customMapRef.current = customMap;
            reloadMap(map);
          });
        });
    } else {
      reloadMap(map);
    }
  };

  // 更新地图类型
  useEffect(() => {
    if (isShowMap) {
      const mapStyle = JStyle[handleMapType(mapType)];
      if (mapStyle) {
        jServerInfo.current = mapStyle;
      } else {
        jServerInfo.current = {
          jServer: handleMapType(mapType),
          baseUrl: justMapBaseURL(mapType),
        };
      }
    }
    setReady(true);
    setJustMapKey(`${height}_${width}_${mapType}`);
  }, [isShowMap, mapType]);

  // 更新地图容器大小
  useEffect(() => {
    if (justMap && justMap.map) {
      const { map } = justMap;
      map.resize();
    }
  }, [width, height]);

  // 更新地图默认设置
  useEffect(() => {
    if (justMap && justMap.map) {
      const { map } = justMap;
      const op = handleMapOptions();
      map.setCenter(op.center);
      map.setZoom(op.zoom);
      map.setMaxZoom(op.maxZoom);
      map.setMinZoom(op.minZoom);
      map.setPitch(op.pitch);
      if (customMapRef.current) {
        customMapRef.current.customMapUpdate(op);
      }
    }
  }, [lng, lat, zoom, minZoom, maxZoom, pitch]);

  return ready ? (
    <>
      {isShowMap && (
        <div style={divStyle}>
          <JMap key={justMapKey} id={id} {...jServerInfo.current} isUpdate loadDone={loadDone} mapOptions={handleMapOptions()}></JMap>
        </div>
      )}
      <div className={styled['child-box']}>{children && children.map((item) => React.cloneElement(item, { justMap, defaultZoom: getZoom() }))}</div>
    </>
  ) : null;
}

EsthesiaDemo.setting = setting;
EsthesiaDemo.styleConfig = {
  selectMap: (props) => <SelectMap {...props} />,
};
EsthesiaDemo.childrenCom = {
  custom_demo_esthesia_scatter: () => import('./components/EScatter'),
  custom_demo_esthesia_analyzeTools: () => import('./components/AnalyzeTools'),
};
export default EsthesiaDemo;
